use std::sync::{Arc, Mutex};

use crate::rtda::Object;

use super::{Class, ArrayObject, class_name_helper::get_component_class_name, ClassLoader};


impl Class {
    pub fn new_array(class: Arc<Class>, count: usize) -> Object {
        if !class.is_array() {
            panic!("Not array class: {}", class.get_name());
        }
        let name = class.get_name();
        match name.as_str() {
            "[Z" => Object::new_array(class, ArrayObject::Byte((0..count).map(|_| i8::default()).collect())),
            "[B" => Object::new_array(class, ArrayObject::Byte((0..count).map(|_| i8::default()).collect())),
            "[C" => Object::new_array(class, ArrayObject::Char((0..count).map(|_| u16::default()).collect())),
            "[S" => Object::new_array(class, ArrayObject::Short((0..count).map(|_| i16::default()).collect())),
            "[I" => Object::new_array(class, ArrayObject::Int((0..count).map(|_| i32::default()).collect())),
            "[J" => Object::new_array(class, ArrayObject::Long((0..count).map(|_| i64::default()).collect())),
            "[F" => Object::new_array(class, ArrayObject::Float((0..count).map(|_| f32::default()).collect())),
            "[D" => Object::new_array(class, ArrayObject::Double((0..count).map(|_| f64::default()).collect())),
            _    => Object::new_array(class, ArrayObject::Object((0..count).map(|_| None).collect()))
        }
    }

    pub fn component_class(&self) -> Arc<Class> {
        let component_class_name = get_component_class_name(self.get_name());
        let loader = self.get_class_loader().unwrap();
        let class = loader.lock().unwrap().load_class(component_class_name);
        class
    }

    pub fn new_byte_array(loader: Arc<Mutex<ClassLoader>>, bytes: Vec<i8>) -> *mut Object {
        let object = Object::new_array(loader.lock().unwrap().load_class("[B".to_string()), ArrayObject::Byte(bytes));
        Box::into_raw(Box::new(object))
    }


}
